/*
   -*- c++ -*-
   virqueue.h

   A virtual queue with each element pointed to a packet
   in the output queue.

 */

#ifndef _virqueue_h
#define _virqueue_h


#include <list>
#include <map>
#include <iostream>

#include "queue.h"


using std::list;
using std::cout;
using std::endl;

/* used to distinguish Large/Small Virtual Queue */
#define PACKET_SIZE_THRESHOLD        100      


/* struct vir_key_t{ */
/*   int nb_id; */
/*   char type; // 'L' or 'S' */
/*   inline bool operator < (const vir_key_t rhs) const {return  */
/*       (nb_id + (int)type) < (rhs.nb_id + (int)rhs.type); */
/*   } */
/* }; */

struct vir_key_t{

    int nb_id;
    char type; // 'L' or 'S'
    inline bool operator < (const vir_key_t rhs) const {
        
	if(nb_id < rhs.nb_id)
	    return true;
	if(nb_id == rhs.nb_id)
	    return (int)type < (int)rhs.type;
	return false;	
    }

};



typedef  std::map<vir_key_t, list<Packet*> *> VirTableType;
typedef  VirTableType::iterator VirTableIter;

class VirQueue {

 public:
    VirQueue();
    ~VirQueue();

    /* 
     * put the packet to virtual queue after enque into the output queue,
     * the virtual queue is specified by next_hop id and packet size.
     * 
     * this will call add_vir_entry if the specific packet queue does not
     * exist.
     */
    void enque_vir_pkt(Packet *, bool);
    /*
     * get the packet queue of a specific virtual queue, the index parameter
     * is Neighbor id and queue type (L or S)
     */
    list<Packet*> * get_vir_pktq(int , char);

    /*
     * delete p from virtual queue when it is dequeued from output queue
     *
     * if the Packet Queue becomes empty after this, call remove_vir_entry
     * to delete the whole entry 
     */
    void remove_vir_pkt(Packet * );
    void show();

 private:
        
    VirTableType vir_table_;
 
};

#endif /*!_virqueue_h*/
